﻿using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using TL_Cloud.API.Helpers;
using TL_Cloud.Core.Entities;
using TL_Cloud.Core.Extensions;
using TL_Cloud.Core.Interfaces;
using TL_Cloud.Core.LinkURL;
using TL_Cloud.Core.Services;
using TL_Cloud.Models.BookShop;
using TL_Cloud.RepositoryInterface.BookShop;
using TL_Cloud.ViewModels.BookShop.BKTypeInfo;

namespace TL_Cloud.API.Controllers
{
    /// <summary>
    /// 图书类型
    /// </summary>
    [Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class BKTypeInfoController : ControllerBase
    {
        private readonly ILogger logger;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IBKTypeInfoRepository _repository;
        private readonly ITypeHelperService _typeHelperService;
        private readonly IPropertyMappingContainer _propertyMappingContainer = null;
        private readonly IMapper _mapper;
        private readonly IUrlHelper _urlHelper;

        public BKTypeInfoController(IMapper mapper,
            ILogger<BKTypeInfoController> logger,
            ITypeHelperService typeHelperService,
            IPropertyMappingContainer propertyMappingContainer,
            IBKTypeInfoRepository repository,
            IUnitOfWork unitOfWork,
            IUrlHelper urlHelper
            )
        {
            this._mapper = mapper;
            this.logger = logger;
            this._typeHelperService = typeHelperService;
            this._repository = repository;
            this._urlHelper = urlHelper;
            this._propertyMappingContainer = propertyMappingContainer;
            this._unitOfWork = unitOfWork;
        }
        /// <summary>
        /// 获取所有的年级数据 
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        [HttpGet(Name = "GetBKTypes")]
        public async Task<IActionResult> Get([FromQuery]BKTypeInfoQueryParameters parameters)
        {

            //判断排序是否存在 ，
            if (!_propertyMappingContainer.ValidateMappingExistsFor<BKTypeInfoResource, Bk_TypeInfo>(parameters.OrderBy))
            {
                return BadRequest("Can't finds fields for sorting.");
            }

            //判断fields参数是否在制定的类型中存在
            if (!_typeHelperService.TypeHasProperties<BKTypeInfoResource>(parameters.Fields))
            {
                return BadRequest("Fields not exist.");
            }

            var dataList = await _repository.GetAllEntitiesAsync(parameters);

            var res = _mapper.Map<IEnumerable<Bk_TypeInfo>, IEnumerable<BKTypeInfoResource>>(dataList);

            //生成 下一个连接和上一个连接的url
            var previousPageLink = dataList.HasPrevious ?
                new LinkUrlCreater<BKTypeInfoQueryParameters>(_urlHelper).CreateGetUrl("GetBKTypoInfos", parameters,
                    PaginationResourceUriType.PreviousPage) : null;

            var nextPageLink = dataList.HasNext ?
               new LinkUrlCreater<BKTypeInfoQueryParameters>(_urlHelper).CreateGetUrl("GetBKTypoInfos", parameters,
                    PaginationResourceUriType.NextPage) : null;


            //数据返回分页数据
            var meta = new
            {
                dataList.TotalItemsCount,
                dataList.PageSize,
                dataList.PageIndex,
                dataList.PageCount,
                previousPageLink,
                nextPageLink
            };

            Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(meta, new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            }));
            //返回结果塑性
            return Ok(res.ToDynamicIEnumerable(parameters.Fields));
        }

        /// <summary>
        /// 获取单个年级数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="fields"></param>
        /// <returns></returns>
        [HttpGet("{id}", Name = "GetBKType")]
        public async Task<IActionResult> Get(string id, string fields = null)
        {
            if (!_typeHelperService.TypeHasProperties<BKTypeInfoResource>(fields))
            {
                return BadRequest("Fields not exist.");
            }
            var entity = await _repository.GetEntityByIdAsync(id);

            if (entity == null)
            {
                return NotFound();
            }

            var Resource = _mapper.Map<Bk_TypeInfo,BKTypeInfoResource>(entity);
            var shapedentityResource = Resource.ToDynamic(fields);
            var links = new LinkUrlCreater<BKTypeInfoQueryParameters>(_urlHelper).CreateLinksForPost("GetBKType", "DeleteBKType", id, fields);
            var result = (IDictionary<string, object>)shapedentityResource;
            result.Add("links", links);
            return Ok(result);
        }

        /// <summary>
        /// 增加科目数据
        /// </summary> 
        [HttpPost(Name = "CreateBKType")]
        public async Task<IActionResult> Post([FromBody] BKTypeBasicResource addResource)
        {
            if (addResource == null)
            {
                return BadRequest();
            }

            if (!ModelState.IsValid)
            {
                return new MyUnprocessableEntityObjectResult(ModelState);
            }

            var entity = _mapper.Map<BKTypeBasicResource, Bk_TypeInfo>(addResource);
            var userinfo = this.GetUserInfo();
            entity.Create(userinfo.Item1, userinfo.Item2);

            _repository.Add(entity);

            if (!await _unitOfWork.SaveAsync())
            {
                throw new Exception("Save Failed!");
            }

            var resultResource = _mapper.Map<Bk_TypeInfo, BKTypeInfoResource>(entity);

            var links = new LinkUrlCreater<BKTypeInfoQueryParameters>(_urlHelper).CreateLinksForPost("GetBKType", "DeleteBKType", entity.BktypeId);
            var linkedPostResource = resultResource.ToDynamic() as IDictionary<string, object>;
            linkedPostResource.Add("links", links);
            return CreatedAtRoute("GetBKType", new { id = linkedPostResource["BktypeId"] }, linkedPostResource);
        }

        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="id"></param>
        [HttpPut("{id}", Name = "UpdateBKType")]
        public async Task<IActionResult> Update(string id, [FromBody] BKTypeUpdateResource updateResource)
        {
            if (updateResource == null)
            {
                return BadRequest();
            }

            if (!ModelState.IsValid)
            {
                return new MyUnprocessableEntityObjectResult(ModelState);
            }

            var BKType = await _repository.GetEntityByIdAsync(id);
            if (BKType == null)
            {
                return NotFound();
            }
            _mapper.Map(updateResource, BKType);
            var userinfo = this.GetUserInfo();
            BKType.Modify(userinfo.Item1, userinfo.Item2);

            if (!await _unitOfWork.SaveAsync())
            {
                throw new Exception($"Updating entity {id} failed when saving.");
            }
            return NoContent();
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("{id}", Name = "DeleteBKType")]
        public async Task<IActionResult> Deleteentity(string id)
        {
            var post = await _repository.GetEntityByIdAsync(id);
            if (post == null)
            {
                return NotFound();
            }
            _repository.Delete(post);

            if (!await _unitOfWork.SaveAsync())
            {
                throw new Exception($"Deleting entity {id} failed when saving.");
            }

            return NoContent();
        }
    }
}